import json
import os
import requests
from PyQt5.QtCore import *
import logging
# import vlc
from playsound import playsound
from os.path import dirname

logging.basicConfig(level=logging.INFO,  # 控制台打印的日志级别
                    filename='music_service.log',
                    filemode='a',  ##模式，有w和a，w就是写模式，每次都会重新写日志，覆盖之前的日志
                    # a是追加模式，默认如果不写的话，就是追加模式
                    format=
                    '%(asctime)s - [line:%(lineno)d] - %(levelname)s: %(message)s'
                    # 日志格式
                    )
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - [line:%(lineno)d] - %(levelname)s: %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)

headers = {
    'Origin': 'https://y.qq.com',
    'Referer': 'https://y.qq.com/portal/search.html',
    'Sec-Fetch-Mode': 'cors',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
}


class MusicThread(QThread):
    def __init__(self, music_info):
        super(MusicThread, self).__init__()
        # music_info的固定句式：
        # 播放陈奕迅的歌
        # 播放陈奕迅的十年
        # 播放白玫瑰
        # 播放流行歌曲
        self.__music_info = music_info
        self.current_song = ''  # 当前正在播放的歌曲：歌名-歌手.mp3
        self.flag = False  # False:现在没有在播放歌曲
        # True：当前正在播放歌曲

    def run(self):
        print('[music_service] ' + self.__music_info)
        # 这里根据__music_info提取出歌手、歌名
        singer_name, music_name = get_singer_song(self.__music_info)
        # logging.debug('子线程，下载并播放音乐')

        # 下载歌曲，播放
        # file_name = 歌名-歌手.mp3
        file_name = download_music(singer=singer_name, song_name=music_name)
        print(file_name)
        # play_song(file_name)


###################################################
# 根据music_info提取出歌手名字、歌名
##################################################
def get_singer_song(music_info):
    singer_name = music_info
    if '的' in music_info:
        # 播放陈奕迅的歌
        # 播放周迅的大鱼
        location = music_info.find('的')
        singer_name = music_info[2:location]
        if '歌' in music_info[location + 1:]:
            music_name = ''
        else:
            music_name = music_info[location + 1:]
    else:
        # 播放十年
        # 播放流行歌曲
        singer_name = ''
        music_name = music_info[2:]

    # TODO
    return singer_name, music_name


###################################################
# 查询音乐
###################################################
def search_music(singer='', song_name=''):
    search_context = singer.strip() + ' ' + song_name.strip()
    PAGE = 1  # 返回第1页
    NUM = 10  # 返回10条结果
    music_info_list = []
    search_url = f'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?p={PAGE}&n={NUM}&w={search_context}'
    response = requests.get(url=search_url).text
    music_json = response[9:-1]
    music_data = json.loads(music_json)

    music_list = music_data['data']['song']['list']
    for music in music_list:
        if 'media_mid' in music:
            music_name = music['songname']  # 歌曲的名字
            singer_name = music['singer'][0]['name']  # 歌手的名字
            songmid = music['songmid']
            media_mid = music['media_mid']
            music_info_list.append((music_name, singer_name, songmid, media_mid))
    return music_info_list


###################################################
# 获取vkey
###################################################
def get_purl(music_info_list):
    music_data = []
    for music in music_info_list:
        music_name = music[0]
        singer_name = music[1]
        songmid = music[2]
        url = 'https://u.y.qq.com/cgi-bin/musicu.fcg?data={"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"8846039534","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"8846039534","songmid":["%s"],"songtype":[0],"uin":"1152921504784213523","loginflag":1,"platform":"20"}},"comm":{"uin":"1152921504784213523","format":"json","ct":24,"cv":0}}' % songmid
        response = requests.get(url).json()  # 如果你获取的数据 是 {}  .json() 他会直接帮我们转换成字典
        purl = response['req_0']['data']['midurlinfo'][0]['purl']
        full_media_url = 'http://dl.stream.qqmusic.qq.com/' + purl
        music_data.append(
            {
                'music_name': music_name,
                'singer_name': singer_name,
                'full_media_url': full_media_url
            }
        )
    return music_data


###################################################
# 返回搜索结果的第一首歌
###################################################
def get_first_song_url(music_data):
    # 找到full_media_url最长的就播放
    # 因为full_media_url可能有两种形式：
    # 第一种：http://dl.stream.qqmusic.qq.com/
    # 第二种：http://dl.stream.qqmusic.qq.com/C400000UBNqe2XHQka.m4a?guid=xxxxx
    # 只有第二种才能播放
    song_full_media_url = ''
    for music in music_data:
        if '.m4a' in music['full_media_url']:
            song_full_media_url = music['full_media_url']
            break

    print(song_full_media_url)
    return song_full_media_url


###################################################
# 返回搜索结果第一首歌的，下载链接
###################################################
def get_first_song_download(music_data):
    for music in music_data:
        if '.m4a' in music['full_media_url']:
            return music


###################################################
# 保存到本地
###################################################
def save_music_mp3(music):
    if not os.path.exists('cache'):  # 判断是否有歌曲下载文件夹
        os.mkdir('cache')  # 如果没有创建 歌曲下载文件夹
    music_name = music['music_name']
    singer_name = music['singer_name']
    full_url = music['full_media_url']
    music_response = requests.get(full_url, headers=headers).content
    # 保存到当前目录下的cache文件夹
    with open('cache/%s-%s.mp3' % (singer_name, music_name), 'wb') as fp:
        fp.write(music_response)
        print('[%s-%s.mp3]保存成功！' % (singer_name, music_name))
    # 返回文件名
    filename = singer_name + '-' + music_name + '.mp3'
    return filename


###################################################
# 根据 歌手 歌名 下载歌曲
# 默认下载陈奕迅的歌（下载搜索结果的第一首音乐）
# @return: 下载歌歌名，格式：歌手-歌名.mp3
###################################################
def download_music(singer='陈奕迅', song_name=''):
    music_info_list = search_music(singer, song_name)
    music_data = get_purl(music_info_list)
    res = get_first_song_download(music_data)
    filename = save_music_mp3(res)
    return filename


###################################################
# 检测歌曲是否以及缓存
###################################################
def exist_music(singer, song_name):
    # TODO 这里要做模糊查询
    filename = 'cache/%s-%s.mp3' % (singer, song_name)
    return os.path.isfile(filename)


###################################################
# 播放音乐
# 如果 本地Cache文件夹已经有该音乐了，就直接播放
# 如果 没有音乐，就下载到Cache再播放
###################################################
def play_music(singer='陈奕迅', song_name=''):
    if exist_music(singer, song_name):
        print('%s-%s.mp3 已经缓存，可以直接播放' % (singer, song_name))
        pass
    else:
        print('%s-%s.mp3 不存在，正在下载歌曲' % (singer, song_name))
        # TODO 这里要加入下载歌曲的代码
        filename = download_music(singer, song_name)
        print("%s 播放" % filename)
        pass


# 旧代码
# def play_song(music_name):
#     file_path = "./cache/" + music_name
#     p = vlc.MediaPlayer(file_path)
#     p.play()


# 停止播放
def stop_song(music_name):
    file_path = "./cache/" + music_name
    # TODO


if __name__ == '__main__':
    play_music("陈奕迅", "黑洞")
